﻿/*
 * logicdevice.cpp
 *
 *  Created on: 2017年11月25日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_SCADA DM_API_EXPORT

#include <dm/scada/logicdevice.hpp>

#include <dm/scada/logicdevicemgr.hpp>
#include <dm/scada/scadainfo.hpp>

#include <dm/scada/statusmgr.hpp>
#include <dm/scada/discretemgr.hpp>
#include <dm/scada/measuremgr.hpp>
#include <dm/scada/cumulantmgr.hpp>
#include <dm/scada/remotectlmgr.hpp>
#include <dm/scada/parametermgr.hpp>
#include <dm/scada/actionmgr.hpp>

#include <dm/scada/event.hpp>
#include <dm/scada/timedmeasure.hpp>
#include <dm/scada/timedcumulant.hpp>

#include <dm/os/log/logger.hpp>

namespace dm{
namespace scada{

static const char* logModule = "CLogicDevice.scada.dm";

/**
 * 通过逻辑设备id构造逻辑设备
 * @param id 逻辑设备id
 */
CLogicDevice::CLogicDevice( const id_t& id ){
	if( id!=Id_Inv ){
		if( !initById(id) ){
			log().warnning(THISMODULE "初始化逻辑设备失败id=%d",id);
		}
	}
}

/**
 * 通过逻辑设备名字构造逻辑设备
 * @param name 逻辑设备名字
 */
CLogicDevice::CLogicDevice( const char* name ){
	if( !initByName(name) ){
		log().warnning(THISMODULE "初始化逻辑设备失败name=%s",name);
	}
}

/**
 * 通过逻辑设备索引号初始化逻辑设备
 * @param idx 逻辑设备索引号
 * @return 是否初始化成功
 */
bool CLogicDevice::initByIndex( const index_t& idx ){
	CLogicDeviceMgr& mgr = CLogicDeviceMgr::ins();

	if( idx<0 || idx>=mgr.size()){
		m_info = NULL;
		m_statusMap = NULL;
		m_discreteMap = NULL;
		m_measureMap = NULL;
		m_cumulantMap = NULL;
		m_remoteCtlMap = NULL;
		m_parameterMap = NULL;
		m_actionMap = NULL;

		m_2logicStatus = NULL;
		m_2logicDiscrete = NULL;
		m_2logicMeasure = NULL;
		m_2logicCumulant = NULL;
		m_2logicRemoteCtl = NULL;
		m_2logicParameter = NULL;
		m_2logicAction = NULL;

		log().warnning(THISMODULE "初始化逻辑设备失败 index=%d",idx);
		return false;
	}else{
		m_info = mgr.info(idx);

		const CScada& scada = CScada::ins();
		m_statusMap = scada.map2Statuses()+m_info->posOfStatus;
		m_discreteMap = scada.map2Discretes()+m_info->posOfDiscrete;
		m_measureMap = scada.map2Measures()+m_info->posOfMeasure;
		m_cumulantMap = scada.map2Cumulants()+m_info->posOfCumulant;
		m_remoteCtlMap = scada.map2RemoteCtls()+m_info->posOfRemoteCtl;
		m_parameterMap = scada.map2Parameters()+m_info->posOfParameter;
		m_actionMap = scada.map2Actions()+m_info->posOfAction;

		m_2logicStatus = scada.map2logicStatuses()+ scada.info()->statusCount()*idx;
		m_2logicDiscrete = scada.map2logicDiscretes()+scada.info()->discreteCount()*idx;
		m_2logicMeasure = scada.map2logicMeasures()+scada.info()->measureCount()*idx;
		m_2logicCumulant = scada.map2logicCumulants()+scada.info()->cumulantCount()*idx;
		m_2logicRemoteCtl = scada.map2logicRemoteCtls()+scada.info()->remoteCtlCount()*idx;
		m_2logicParameter = scada.map2logicParameters()+scada.info()->parameterCount()*idx;
		m_2logicAction = scada.map2Actions()+scada.info()->actionCount()*idx;

		return true;
	}
}

/**
 * 通过逻辑设备id初始化逻辑设备
 * @param id 逻辑设备id
 * @return
 */
bool CLogicDevice::initById( const id_t& id ){
	return initByIndex( CLogicDeviceMgr::ins().indexById(id));
}

/**
 * 通过逻辑设备名字初始化逻辑设备
 * @param name 逻辑设备名字
 * @return
 */
bool CLogicDevice::initByName( const char* name ){
	return initByIndex( CLogicDeviceMgr::ins().indexByName(name));
}

/**
 * 获取逻辑设备的状态信息
 * @param idx 逻辑设备的状态量索引
 * @return
 */
const SStatusInfo* CLogicDevice::statusInfo( const index_t& idx )const{
	if( m_info==NULL || m_statusMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfStatus )
		return NULL;

	return CStatusMgr::ins().info(m_statusMap[idx]);
}

/**
 * 获取逻辑设备的离散量信息
 * @param idx 逻辑设备的离散量索引
 * @return
 */
const SDiscreteInfo* CLogicDevice::discreteInfo( const index_t& idx )const{
	if( m_info==NULL || m_discreteMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfDiscrete )
		return NULL;
	return CDiscreteMgr::ins().info(m_discreteMap[idx]);
}

/**
 * 获取逻辑设备测量量信息
 * @param idx 逻辑设备测量量索引
 * @return
 */
const SMeasureInfo* CLogicDevice::measureInfo( const index_t& idx )const{
	if( m_info==NULL || m_measureMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfMeasure )
		return NULL;
	return CMeasureMgr::ins().info(m_measureMap[idx]);
}

/**
 * 获取逻辑设备累计量信息
 * @param idx 逻辑设备累计量索引
 * @return
 */
const SCumulantInfo* CLogicDevice::cumulantInfo( const index_t& idx )const{
	if( m_info==NULL || m_cumulantMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfCumulant )
		return NULL;
	return CCumulantMgr::ins().info(m_cumulantMap[idx]);
}

/**
 * 获取逻辑设备远控信息
 * @param idx 逻辑设备远控索引
 * @return
 */
const SRemoteCtlInfo* CLogicDevice::remoteCtlInfo( const index_t& idx )const{
	if( m_info==NULL || m_remoteCtlMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfRemoteCtl )
		return NULL;
	return CRemoteCtlMgr::ins().info(m_remoteCtlMap[idx]);
}

/**
 * 获取逻辑设备参数信息
 * @param idx 逻辑设备参数索引
 * @return
 */
const SParaInfo* CLogicDevice::parameterInfo( const index_t& idx )const{
	if( m_info==NULL || m_parameterMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfParameter )
		return NULL;
	return CParameterMgr::ins().info(m_parameterMap[idx]);
}

/**
 * 获取逻辑设备动作信息
 * @param idx 逻辑设备动作索引
 * @return
 */
const SActionInfo* CLogicDevice::actionInfo( const index_t& idx )const{
	if( m_info==NULL || m_actionMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return NULL;
	}

	if( idx<0 || idx>=m_info->sizeOfAction )
		return NULL;
	return CActionMgr::ins().info(m_actionMap[idx]);
}

/**
 * 获取逻辑设备的物理状态量索引
 * @param logic 逻辑设备状态量索引
 * @return
 */
index_t CLogicDevice::physicalStatus( const index_t& logic )const{
	if( m_info==NULL || m_statusMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfStatus )
		return Idx_Inv;
	return m_statusMap[logic];
}

/**
 * 获取逻辑设备的物理离散量索引
 * @param logic 逻辑设备离散量索引
 * @return 物理索引
 */
index_t CLogicDevice::physicalDiscrete( const index_t& logic )const{
	if( m_info==NULL || m_discreteMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfDiscrete )
		return Idx_Inv;
	return m_discreteMap[logic];
}

/**
 * 获取逻辑设备的测量量的物理索引
 * @param logic 逻辑设备的测量量索引
 * @return
 */
index_t CLogicDevice::physicalMeasure( const index_t& logic )const{
	if( m_info==NULL || m_measureMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfMeasure )
		return Idx_Inv;
	return m_measureMap[logic];
}

/**
 * 获取逻辑设备的累计量的物理索引
 * @param logic 逻辑设备的累计量索引
 * @return
 */
index_t CLogicDevice::physicalCumulant( const index_t& logic )const{
	if( m_info==NULL || m_cumulantMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfCumulant )
		return Idx_Inv;
	return m_cumulantMap[logic];
}

/**
 * 获取逻辑设备的远控的物理索引
 * @param logic 逻辑设备的远控索引
 * @return
 */
index_t CLogicDevice::physicalRemoteCtl( const index_t& logic )const{
	if( m_info==NULL || m_remoteCtlMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfRemoteCtl )
		return Idx_Inv;
	return m_remoteCtlMap[logic];
}

/**
 * 获取逻辑设备的参数的物理索引
 * @param logic 逻辑设备的参数索引
 * @return
 */
index_t CLogicDevice::physicalParameter( const index_t& logic )const{
	if( m_info==NULL || m_parameterMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfParameter )
		return Idx_Inv;
	return m_parameterMap[logic];
}

/**
 * 获取逻辑设备的动作的物理索引
 * @param logic 逻辑设备的动作索引
 * @return
 */
index_t CLogicDevice::physicalAction( const index_t& logic )const{
	if( m_info==NULL || m_actionMap==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	if( logic<0 || logic>=m_info->sizeOfAction )
		return Idx_Inv;
	return m_actionMap[logic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalStatus( const index_t& physic )const{
	if( m_info==NULL || m_2logicStatus==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->statusCount() )
		return Idx_Inv;

	return m_2logicStatus[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalDiscrete( const index_t& physic )const{
	if( m_info==NULL || m_2logicDiscrete==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->discreteCount() )
		return Idx_Inv;

	return m_2logicDiscrete[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalMeasure( const index_t& physic )const{
	if( m_info==NULL || m_2logicMeasure==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->measureCount() )
		return Idx_Inv;

	return m_2logicMeasure[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalCumulant( const index_t& physic )const{
	if( m_info==NULL || m_2logicCumulant==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->cumulantCount() )
		return Idx_Inv;

	return m_2logicCumulant[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalRemoteCtl( const index_t& physic )const{
	if( m_info==NULL || m_2logicRemoteCtl==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->remoteCtlCount() )
		return Idx_Inv;

	return m_2logicRemoteCtl[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalParameter( const index_t& physic )const{
	if( m_info==NULL || m_2logicParameter==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->parameterCount() )
		return Idx_Inv;

	return m_2logicParameter[physic];
}

/**
 * 将物理量映射到逻辑量
 * @param physic 物理索引号
 * @return 返回逻辑索引号
 * - Idx_Inv 无效索引号
 */
index_t CLogicDevice::logicalAction( const index_t& physic )const{
	if( m_info==NULL || m_2logicAction==NULL ){
		log().warnning(THISMODULE "逻辑设备未正确初始化");
		return Idx_Inv;
	}

	const CScada& scada = CScada::ins();
	if( physic<0 || physic>=scada.info()->actionCount() )
		return Idx_Inv;

	return m_2logicAction[physic];
}

/**
 * 将事件转换成逻辑设备的点表
 * @param ev
 * @return
 */
bool CLogicDevice::chg2logicEvent( CEvent& ev )const{
	switch( ev.type ){
	case CEvent::Status:
		ev.idx = logicalStatus(ev.idx);
		break;
	case CEvent::Discrete:
		ev.idx = logicalDiscrete(ev.idx);
		break;
	case CEvent::Action:
		ev.idx = logicalAction(ev.idx);
		break;
	case CEvent::MeasureAlarm:
		ev.idx = logicalMeasure(ev.idx);
		break;
	case CEvent::CumulantAlarm:
		ev.idx = logicalCumulant(ev.idx);
		break;
	default:
		log().warnning(THISMODULE "未知类型:%d",ev.type);
		return true;
	}

	return ev.idx!=Idx_Inv;
}

/**
 * 将时标测量量转换成逻辑设备的点表
 * @param tm
 * @return
 */
bool CLogicDevice::chg2logicMeasure( CTimedMeasure& tm )const{
	tm.setIndex( logicalMeasure(tm.getIndex()));
	return Idx_Inv!=tm.getIndex();
}

/**
 * 将时标累计量转换成逻辑设备的点表
 * @param tc
 * @return
 */
bool CLogicDevice::chg2logicCumulant( CTimedCumulant& tc )const{
	tc.setIndex( logicalCumulant(tc.getIndex()));
	return Idx_Inv!=tc.getIndex();
}

/**
 * 获取逻辑设备状态量实时值
 * @param idx 逻辑状态量索引
 * @return
 */
const CLogicDevice::status_t* CLogicDevice::status( const index_t& idx )const{
	return CStatusMgr::ins().rt(physicalStatus(idx));
}

/**
 * 获取逻辑设备离散量实时值
 * @param idx 逻辑离散量索引
 * @return
 */
const CLogicDevice::discrete_t* CLogicDevice::discrete( const index_t& idx )const{
	return CDiscreteMgr::ins().rt(physicalDiscrete(idx));
}

/**
 * 获取逻辑设备测量值实时值
 * @param idx 逻辑测量量索引
 * @return
 */
const CLogicDevice::measure_t* CLogicDevice::measure( const index_t& idx )const{
	return CMeasureMgr::ins().rt(physicalMeasure(idx));
}

/**
 * 获取逻辑设备累计量实时值
 * @param idx 逻辑累计量索引
 * @return
 */
const CLogicDevice::cumulant_t* CLogicDevice::cumulant( const index_t& idx )const{
	return CCumulantMgr::ins().rt(physicalCumulant(idx));
}

}
}


